package main

import (
	"fmt"
	"github.com/PuerkitoBio/goquery"
	"github.com/xuri/excelize/v2"
	_ "image/gif"
	_ "image/jpeg"
	_ "image/png"
	"io/ioutil"
	"log"
	"net/http"
	"regexp"
	"strconv"
	"sync"
	"time"
)

var wg = &sync.WaitGroup{}

func main() {
	data := make([][]string, 0)
	data = append(data, []string{"标题", "发布日期", "阅读数", "封面"})

	index := SignWebHtml("https://www.aquanliang.com/blog")
	data = append(data, index...)

	for i := 2; i <= 49; i++ {
		tmp := SignWebHtml("https://www.aquanliang.com/blog/page/" + strconv.Itoa(i))
		data = append(data, tmp...)
	}

	Write(data, "output.xlsx")

	log.Println("程序完成")
}

// SignWebHtml 获取网站信息 单个页面
func SignWebHtml(url string) (resData [][]string) {
	log.Println("获取 " + url + " 数据")
	resData = make([][]string, 0)
	re, _ := regexp.Compile("\\<[\\S\\s]+?\\>")
	imgre := regexp.MustCompile("((ht|f)tps?):\\/\\/[\\w\\-]+(\\.[\\w\\-]+)+([\\w\\-\\.,@?^=%&:\\/~\\+#]*[\\w\\-\\@?^=%&\\/~\\+#])?")
	//<img\s+[^>]*\s*src\s*=\s*([']?)(?<url>\S+)'?[^>]*>
	res, err := http.Get(url)
	if err != nil {
		log.Fatal(err)
	}

	defer res.Body.Close()
	if res.StatusCode != 200 {
		log.Fatalf("status code error: %d %s", res.StatusCode, res.Status)
	}

	doc, err := goquery.NewDocumentFromReader(res.Body)
	if err != nil {
		log.Fatal(err)
	}

	doc.Find(".ant-layout-content").Each(func(i int, s *goquery.Selection) {
		div := s.Find("section > div").Last()

		div.Find("div > div > span").Each(func(j int, span *goquery.Selection) {
			if j > 9 {
				return
			}
			var itemData = make([]string, 0)

			//标题 发布日期 阅读数
			span.Find("div > div").Each(func(k int, spanDiv *goquery.Selection) {
				title := spanDiv.Find("a > div").Text()
				if title == "" {
					return
				}
				fTime := ""
				readNum := ""
				//fmt.Println(title)
				spanDiv.Find("div > div").Each(func(timeDivIndex int, timeDiv *goquery.Selection) {

					if timeDivIndex == 1 {
						timeDiv.Find("div").Each(func(timeDivDivIndex int, timeDivDiv *goquery.Selection) {
							//fmt.Println(timeDivDivIndex, timeDivDiv.Text())
							if timeDivDivIndex == 1 {
								fTime = re.ReplaceAllString(timeDivDiv.Text(), "")
							}
							if timeDivDivIndex == 6 {
								readNum = re.ReplaceAllString(timeDivDiv.Text(), "")
							}
						})
					}
				})
				itemData = append(itemData, title, fTime, readNum)
			})

			imaArr := imgre.FindStringSubmatch(span.Find("a > div > div > div").Text())
			if len(imaArr) > 0 {
				itemData = append(itemData, imaArr[0])
			}

			if len(itemData) > 0 {
				resData = append(resData, itemData)
			}
		})

	})
	return
}

func Write(msg [][]string, filePath string) {
	excel := excelize.NewFile()
	for i, menu := range msg {
		axis := fmt.Sprintf("A%d", i+1)
		tmpMenu := menu
		if len(menu) == 4 && i > 0 {
			tmpMenu = menu[:len(menu)-1]
		}
		err := excel.SetSheetRow("Sheet1", axis, &tmpMenu)
		if i >= 1 {
			if len(menu) == 4 {
				wg.Add(1)
				go AddImgToExcel(excel, "Sheet1", fmt.Sprintf("D%d", i+1), menu[3])
			}
		}
		if err != nil {
			panic(err)
		}
	}
	log.Println("正在写入图片，请稍等......")
	wg.Wait()
	err := excel.SaveAs(filePath)
	if err != nil {
		panic(err)
	}
	return
}

func AddImgToExcel(xlsx *excelize.File, sheet, location string, imgpath string) error {
	defer wg.Done()
	log.Println("写入图片：" + imgpath + "位置：" + location)
	res, err := http.Get(imgpath)
	if err != nil {
		// 如果有错误返回错误内容
		log.Panic(err)
		return err
	}
	// 使用完成后要关闭，不然会占用内存
	defer res.Body.Close()
	// 读取字节流
	bytes, err := ioutil.ReadAll(res.Body)
	if err != nil {
		log.Panic(err)
		return err
	}

	format := fmt.Sprintf(`{
		"autofit":true,
        "hyperlink": "%s",
        "hyperlink_type": "External",
        "print_obj": true,
        "lock_aspect_ratio": false,
        "locked": false,
        "positioning": "oneCell"
    }`, imgpath)
	// err = xlsx.AddPicture(sheet, location, outname, `{"lock_aspect_ratio": true, "locked": true, "positioning": "absolute"}`)//oneCell
	err = xlsx.AddPictureFromBytes(sheet, location, format, time.Now().String(), ".jpg", bytes)
	if err != nil {
		log.Println("AddPicture err  :", err)
		return err
	}
	return nil
}
